#include "app_timer.h"


App_Timer_Object App_software_timer[TIMER_MAX];

unsigned int App_System_1ms_tick;


void App_Timer_Init()
{
    App_System_1ms_tick = 0;
    if (SysTick_Config(SystemCoreClock / 1000))
    {
        // 配置失败时进入死循环
        while (1);
    } 
    // 配置SysTick中断优先级（最低优先级）
    NVIC_SetPriority(SysTick_IRQn, 0x0F);
}
void App_SysTick_Handler(void)
{
    if (App_System_1ms_tick >= 0xFFFFFFFF)
    {
        App_System_1ms_tick = 0;
    }
    else
    {
        App_System_1ms_tick++;
    }
}

unsigned int App_ticket_1ms_Get(void)
{
    return App_System_1ms_tick;
}



void App_Timer_delay_ms(unsigned int timer_ticket_long)
{
    Start_App_Software_Timer(SYSTEM_TIMER, timer_ticket_long);
    while (App_Software_Timer_Status(SYSTEM_TIMER) == APP_TM_RUNNING);

}
void Start_App_Software_Timer(unsigned char Timer_No, unsigned int Timer_ticket_long)
{
    unsigned int now_tickets = App_ticket_1ms_Get();
    set_timer_status(Timer_No, APP_TM_RUNNING);
    set_timer_begin_tickets(Timer_No, now_tickets);
    set_timer_need_elapsed_tickets(Timer_No, Timer_ticket_long);
}
void Suspend_App_Software_Timer(unsigned char Timer_No)
{
    unsigned int remain_tickets = 0;
    if (Get_App_Software_Timer_Info(Timer_No, &remain_tickets) == APP_TM_RUNNING)
    {
        set_timer_status(Timer_No, APP_TM_SUSPENSIVE);
        store_timer_remain_tickets(Timer_No, remain_tickets);
    }
}
void Continue_App_Software_Timer(unsigned char Timer_No)
{
    unsigned int remain_tikets = 0;
    Get_App_Software_Timer_Info(Timer_No, &remain_tikets);
    Start_App_Software_Timer(Timer_No, remain_tikets);

}
unsigned char App_Software_Timer_Status(unsigned char Timer_No)
{
    unsigned int remain_tickets;
    return Get_App_Software_Timer_Info(Timer_No, &remain_tickets);
}
static unsigned int get_timer_begin_tickets(unsigned char Timer_No)
{
    return App_software_timer[Timer_No].timer_begine_tickets;
}
static unsigned int get_timer_need_elapsed_tickets(unsigned char Timer_No)
{
    return App_software_timer[Timer_No].timer_tickets_long;
}
static unsigned int get_timer_stored_remian_tickets(unsigned char Timer_No)
{
    return App_software_timer[Timer_No].store_suspend_remain_tickets;
}
static unsigned char get_timer_status(unsigned char Timer_No)
{
    return App_software_timer[Timer_No].timer_statuse;
}




static void set_timer_begin_tickets(unsigned int Timer_No, unsigned int begin_tickets)
{
    App_software_timer[Timer_No].timer_begine_tickets = begin_tickets;
}
static void set_timer_need_elapsed_tickets(unsigned int Timer_No, unsigned int need_elapsed_tickets)
{
    App_software_timer[Timer_No].timer_tickets_long = need_elapsed_tickets;
}
static void store_timer_remain_tickets(unsigned int Timer_No, unsigned int remain_tickets)
{
    App_software_timer[Timer_No].store_suspend_remain_tickets = remain_tickets;
}

void set_timer_status(unsigned char Timer_No, unsigned char status)
{
    App_software_timer[Timer_No].timer_statuse = status;
}


static unsigned char calculate_tickets(unsigned int begin_tickets, unsigned int now_tickets, unsigned int need_elapsed_tickets, unsigned int* remain_tickets)
{
    unsigned int tmp;
    if ((0xFFFFFFFF - begin_tickets) <= need_elapsed_tickets)
    {

        if (now_tickets > begin_tickets)
        {
            *remain_tickets = (need_elapsed_tickets - (now_tickets - begin_tickets));
            return 1;
        }
        else
        {
            tmp = now_tickets + (0xFFFFFFFF - begin_tickets);
            if (tmp >= need_elapsed_tickets)
            {
                *remain_tickets = 0;
                return 0;
            }
            else
            {
                *remain_tickets = need_elapsed_tickets - tmp;
                return 1;
            }
        }
    }
    else
    {
        tmp = now_tickets - begin_tickets;
        if (tmp >= need_elapsed_tickets)
        {
            *remain_tickets = 0;
            return 0;
        }
        else
        {
            *remain_tickets = need_elapsed_tickets - tmp;
            return 1;
        }
    }
}

unsigned char Get_App_Software_Timer_Info(unsigned char Timer_No, unsigned int* tickets_remain)
{
    unsigned char status = get_timer_status(Timer_No);
    unsigned int need_elapsed_tickets = get_timer_need_elapsed_tickets(Timer_No);
    unsigned int begin_tickets = get_timer_begin_tickets(Timer_No);
    unsigned int now_tickets = App_ticket_1ms_Get();
    switch (status)
    {
    case APP_TM_STANDBY:
        *tickets_remain = 0;
        return APP_TM_STANDBY;
    case APP_TM_RUNNING:
        if (calculate_tickets(begin_tickets, now_tickets, need_elapsed_tickets, tickets_remain))
        {
            return APP_TM_RUNNING;
        }
        else
        {
            set_timer_status(Timer_No, APP_TM_STANDBY);
            return APP_TM_RUNNING_OUT;
        }
    case APP_TM_SUSPENSIVE:
        *tickets_remain = get_timer_stored_remian_tickets(Timer_No);
        return APP_TM_SUSPENSIVE;
    default:
        *tickets_remain = 0;
        return APP_TM_STANDBY;
    }

}
void Stop_App_Software_Timer(unsigned char Time_No)
{
    App_software_timer[Time_No].timer_statuse = APP_TM_STANDBY;
}
